"""
线性回归
"""

import numpy as np
import matplotlib.pyplot as plt

# 房子面积 年龄 性别
data = np.array(
    [[100, 32, 1],
     [90, 23, 1],
     [150, 45, 0],
     [60, 40, 1],
     [80, 42, 0],])

# 贷款金额 5行一列
labels = np.array([[20], [24], [50], [15], [10],])


class LinearRegression:

    def __init__(self, data, labels):
        self.data = data
        self.labels = labels

        # 特征数量
        num_features = self.data.shape[1]

        # 3行1列的矩阵
        self.theta = np.zeros((num_features, 1))
        print(self.theta)

    def train(self, alpha, num_iterations):
        lossList = self.gradient_descent(alpha, num_iterations)
        return self.theta, lossList

    def gradient_descent(self, alpha, num_iterations):
        loss_his = []
        for _ in range(num_iterations):
            error = self.gradient_step(alpha)
            loss_his.append(error)

        return loss_his

    def gradient_step(self, alpha):
        num_examples = self.data.shape[0]
        prediction = self.hypothesis(self.data, self.theta)
        delta = prediction - self.labels
        theta = self.theta
        theta = theta - alpha * (1 / num_examples) * np.dot(delta.T, self.data).T
        self.theta = theta

        error = np.dot(delta.T, delta) / (2 * num_examples)
        return error[0][0]

    @staticmethod
    # 静态方法不需要创建类的实例就可以调用,常用在定义一个与类相关但不需要访问类或实例数据的方法时
    def hypothesis(data, theta):
        prediction = np.dot(data, theta)
        return prediction

    def get_loss(self, data, labels):
        prediction = LinearRegression.hypothesis(data, self.theta)
        delta = prediction - labels
        return delta


dj = LinearRegression(data, labels)
res = dj.train(0.00001, 1000)
print(res[0])
print(res[1])


plt.scatter(range(1000), res[1])
plt.show()
